home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #include <unistd.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <limits.h>
- #include "askrunlevel.h"
- #include "internal.h"
- #include <ncurses/curses.h>
- #include "../misc/misc.h"
- #include "../xconf/xconf.h"
- #include "../netconf/netconf.h"
- #include "../userconf/userconf.h"
- #include "../main/main.h"
- #include "../fstab/fstab.h"
- #include "../paths.h"
- #include "askrunlevel.m"
-
- static HELP_FILE help_askrun (HELP_ASKRUN,"intro");
- static HELP_FILE help_boot (HELP_ASKRUN,"boot");
-
-
- /* #Specification: askrunlevel / intro
- When linux boot, it start /sbin/init which does some
- basic initialisation, then try to jump to its default
- run level. If this default run level is not defined and
- /sbin/askrunlevel do exist, then it is execute.
-
- The purpose of this program is to let the user select the
- run level in a meaningful way. Instead of numbers, it
- present a menu of configuration useful for a workstation.
- Also, askrunlevel try to validate which configuration are
- possible. There is no need to ask the user if he want to
- start X automatically (using xdm) unless X has been configured.
-
- To make it easy for the user, askrunlevel act also has a first
- time configuration utility. So if a configuration do not exist
- it let the user configure it right away. No need to boot twice
- (once to configure, and once to activate the configuration).
-
- If the user do not select anything in a specific time, the
- default run level is activate.
-
- The future will tell if this is true...
- */
-
- static void askrunlevel_saynographic(const char *status_graphic)
- {
- xconf_error (MSG_U(E_GRAPH,"Can't do this\n"
- "because the Graphic mode is not yet\n"
- "configured\n\n%s"),status_graphic);
- }
- static void askrunlevel_saynographic_net(
- char *status_graphic,
- char *status_net)
- {
- xconf_error (MSG_U(E_GRAPHNET,"Can't do this\n"
- "because the Graphic mode\n"
- "and the Networking are not yet\n"
- "configured\n\n%s\n\n%s"),status_graphic,status_net);
- }
- static void askrunlevel_saynonet(char *status_net)
- {
- xconf_error (MSG_U(E_NET,"Can't do this\n"
- "because the Networking is not yet\n"
- "configured\n\n%s"),status_net);
- }
-
- /*
- Activate the timeout only if the system is freshly start.
- If uptime is old enough, it means askrunlevel was called
- after the user explicitly told init to do so, so the timeout
- feature is not useful here.
-
- Return the timeout value (in seconds) or 0.
- */
- static int askrunlevel_enabletimeout(ASK_PARM &parm)
- {
- FILE *fin = xconf_fopen ("/proc/uptime","r");
- int timeout = 0;
- // We assume that if /proc/uptime is not available, better
- // play safe and disable the timeout feature.
- if (fin != NULL){
- /* #Specification: askrunlevel / automatic booting / timeout
- linuxconf will automaticly boot the system into
- the default runlevel (as configured) only
- if it is called at boot time (when called as /sbin/askrunlevel).
-
- There is two possibilities: Either the boot
- was normal (ie. fairly fast) or fairly slow
- (the system had to do a fsck after a crash).
- In the first case, it will boot as configured
- after the specified timeout.
-
- If the system took more than 60 seconds to boot
- it will still boot by itself, but will selected
- a timeout of one minute. The system will
- also activate the bell.
-
- This is to catch the attention of the
- operator.
- */
- long uptime;
- if (fscanf (fin,"%ld",&uptime)==1){
- timeout = parm.timeout;
- if(uptime > 60 && timeout != 0){
- timeout = 60;
- for (int i=0; i<2; i++){
- putchar ('\a');
- fflush (stdout);
- sleep(1);
- }
- }
- dialog_settimeout (timeout,MENU_ESCAPE,false);
- }else{
- xconf_error (MSG_U(E_PROCUPTIME,"Can't parse /proc/uptime\n"));
- }
- fclose (fin);
- }
- return timeout;
- }
-
- /*
- Configure the default runlevel.
- */
- void askrunlevel_config()
- {
- char status_graphic[2000];
- int graphic_ok = xconf_xok(status_graphic);
- char status_net[2000];
- int net_ok = netconf_netok(status_net) != NULL;
- int choice = 0;
- while (1){
- RUNLEVELS runlevels (graphic_ok,net_ok);
- static const char *lilo_conf = MSG_U(M_LILO,"LILO (Linux boot loader)");
- static const char *lilo_default = MSG_U(M_DEFLILO,"default boot configuration");
- static const char *lilo_confaddany = MSG_U(M_NEWKERN,"a new kernel");
- static const char *lilo_confaddcompil = MSG_U(M_COMPILED,"a kernel you have compiled");
- static const char *config_mode = MSG_U(M_DEFBOOT,"default boot mode");
- static const char *config_define = MSG_U(M_RUNLEVELS,"runlevels");
-
- static const char *menuopt[]={
- MSG_U(M_CONFIG,"Configure"), lilo_conf,
- MSG_U(M_CHANGE,"Change"), lilo_default,
- MSG_U(M_ADDLILO,"Add to LILO"), lilo_confaddany,
- " ", lilo_confaddcompil,
- "-", "",
- " ", config_mode,
- MSG_U(M_DEFINE,"Define"), config_define,
- NULL
- };
- MENU_STATUS code = xconf_menu (
- MSG_U(T_BOOTCONF,"Boot configuration")
- ,MSG_U(I_BOOTCONF,"You are allowed to define the default\n"
- "boot mode of this computer")
- ,help_boot
- ,menuopt,choice);
- if (code != MENU_OK){
- break;
- }else{
- const char *key = menuopt[choice*2+1];
- if (key == config_mode){
- runlevels.config();
- }else if (key == lilo_conf){
- lilo_edit();
- }else if (key == lilo_default){
- lilo_setdefault();
- }else if (key == lilo_confaddany){
- lilo_addany();
- }else if (key == lilo_confaddcompil){
- lilo_addcompil();
- }else if(key == config_define){
- runlevels.define();
- }
- }
- }
- }
-
- static int askrunlevel_chkterm ()
- {
- int ret = -1;
- const char *pt = getenv ("TERM");
- if (pt != NULL){
- char path[PATH_MAX];
- sprintf (path,"/usr/lib/terminfo/%c/%s",*pt,pt);
- if (file_exist (path)) ret = 0;
- }
- return ret;
- }
-
- static void askrunlevel_setterm()
- {
- /* #Specification: askrunlevel / terminal type
- askrunlevel is called very early at boot time. At this
- time the TERM environnement variable is set directly by
- the kernel (it can be overriden by init I think). In
- kernel 1.2.x, it is generally set to "con80x25". In newer
- kernel, it is set to "linux".
-
- Many (Most) system out there simply do not have a
- definition in /usr/lib/terminfo for such a TERM type.
-
- When starting askrunlevel, we check if the TERM variable
- do point to something in /usr/lib/terminfo. If not, TERM
- is silently set to "linux". If linux is not defined, it
- is set to "console". This should cover most cases.
- */
- if (askrunlevel_chkterm()==-1){
- putenv ("TERM=linux");
- if (askrunlevel_chkterm()==-1){
- putenv ("TERM=console");
- if (askrunlevel_chkterm()==-1){
- RUNLEVELS runlevels(0,0);
- runlevels.setlevel (4);
- printf (MSG_U(E_TERMINFO
- ,"No valid TERM definition\n"
- "probably caused by an improperly installed\n"
- "terminfo database.\n"));
- exit (-1);
- }
- }
- }
- }
-
- int askrunlevel_main (int , char *[])
- {
- modules_dummy(); // Just to ease the link
- askrunlevel_setterm();
- /* Specification: askrunlevel / principal
- The user must select one of these choice
-
- Start in graphic mode
- graphic mode and network
- text mode
- text mode and network
- maintenance mode
- Set the default boot mode
- Set the timeout value
- */
- ASK_PARM parm;
- boot_save2log();
- /* Specification: askrunlevel / time & cmos
- askrunlevel grab the time from cmos right at boot
- time. The /sbin/clock command in most /etc/rc.d/rc.S
- is useless.
- */
- datetime_getfromcmos();
- modules_check();
- dialog_settimeout (15,MENU_ESCAPE,true);
- fstab_check(); // Check /etc/fstab
- fstab_checkmount(1); // mount local filesystems
- configf_booterase(); // some cleanup
- fixperm_check_boot(); // check some permissions
- askrunlevel_readparm (parm);
- dialog_settimeout (0,MENU_ESCAPE,false);
- // Conditionnally activate the timeout
- // firsttime toggle the message about the timeout
- int timeout = askrunlevel_enabletimeout (parm);
- int choice = parm.defmode;
- while (1){
- static const char *set_config = MSG_U(M_TWORKSTATION,"the workstation");
- static const char *boot_log = MSG_U(M_BOOTLOGS,"the boot logs");
- static const char *menuopt[]={
- MSG_U(M_START,"Start"), NULL,
- " ", NULL,
- " ", NULL,
- " ", NULL,
- " ", NULL,
- " ", NULL,
- MSG_R(M_CONFIG), set_config,
- MSG_U(M_VIEW,"View"), boot_log,
- NULL
- };
- char status_graphic[2000];
- int graphic_ok = xconf_xok(status_graphic);
- char status_net[2000];
- int net_ok = netconf_netok(status_net) != NULL;
- RUNLEVELS runlevels (graphic_ok,net_ok);
- runlevels.setmenu (menuopt);
- char infohelp[500];
- strcpy (infohelp,MSG_U(I_SELONE
- ,"Select one of the operation mode below\n"
- "or configure the default mode"));
- if (timeout != 0){
- sprintf (infohelp+strlen(infohelp)
- ,MSG_U(I_WARN,"\n"
- "Unless you select something within %d seconds\n"
- "\"%s\" will start automaticly")
- ,timeout,menuopt[choice*2+1]);
- }
- timeout = 0;
- MENU_STATUS code = xconf_menu (MSG_U(T_OPERMODE,"Operation mode")
- ,infohelp
- ,help_askrun
- ,menuopt,choice);
- if (code != MENU_OK){
- runlevels.setlevel(parm.defmode);
- break;
- }else{
- const char *key = menuopt[choice*2+1];
- if (key == set_config){
- if (perm_checkpass()){
- linuxconf_main(1);
- askrunlevel_readparm (parm);
- }
- }else if (key == boot_log){
- boot_showlog();
- }else{
- RUNLEVEL *ptrun = runlevels.tbrun + choice;
- if (!ptrun->graphic_err && !ptrun->net_err){
- if (ptrun->init_runlevel != 'S'
- || perm_checkpass()){
- runlevels.setlevel(choice);
- break;
- }
- }else if (ptrun->graphic_err
- && ptrun->net_err){
- askrunlevel_saynographic_net(status_graphic,status_net);
- }else if (ptrun->graphic_err){
- askrunlevel_saynographic(status_graphic);
- }else{
- askrunlevel_saynonet(status_net);
- }
- }
- }
- }
- return 0;
- }
-
-